﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using WinnerCMS.BLL.PageFactory;
using WinnerCMS.Common;
using WinnerCMS.Data;
using WinnerCMS.Model;
using WinnerCMS.Model.Enum;

#endregion

namespace WinnerCMS.BLL
{
    /// <summary>
    /// 栏目管理
    /// </summary>
    public class CategoryManage : MarshalByRefObject
    {
        private static readonly CategoryDal Dal;
        private static Dictionary<int, Category> _alllist;

        #region 构造函数

        static CategoryManage()
        {
            Dal = new CategoryDal();
        }

        #endregion

        #region 添加栏目

        /// <summary>
        /// 添加栏目
        /// </summary>
        /// <param name="model"></param>
        /// <param name="fields"></param>
        /// <returns></returns>
        [Logging, ExceptionCall]
        public Result Save(Category model, IList<string> fields)
        {
            Result resu = new Result();

            #region 验证

            if (model.CategoryName.Length == 0)
            {
                resu.Errors = "必须填写栏目名称";
                return resu;
            }
            if (model.ModelId == 0)
            {
                resu.Errors = "必须选择模型。";
                return resu;
            }
            if (model.FilePostfix.Length == 0 && model.UrlStyle == 0)
            {
                resu.Errors = "“浏览页扩展名”不能为空！";
                return resu;
            }

            if (model.CategoryFilePostfix.Length == 0 && model.CategoryUrlStyle == 0)
            {
                resu.Errors = "“栏目页扩展名”不能为空！";
                return resu;
            }
            if (model.TemplateFileName.IsNullOrEmpty())
            {
                resu.Errors = "“栏目页模板”不能为空！";
                return resu;
            }
            if (model.ShowPageTemplateFileName.IsNullOrEmpty())
            {
                resu.Errors = "“详情页模板”不能为空！";
                return resu;
            }

            #endregion

            if (model.Id == 0)
            {
                model.Id = Dal.Add(model);
                BuildUrlFormat(model);
                Dal.Edit(model);
                resu.LogMessage = "添加栏目" + model.CategoryName;
            }
            else
            {
                BuildUrlFormat(model);
                Dal.Edit(model);
                resu.LogMessage = "修改栏目，ID：" + model.Id + " 为 " + model.CategoryName;
            }

            _alllist = null;

            ClearCache();
            return resu;
        }

        #endregion

        #region 获取栏目

        /// <summary>
        /// 获取栏目
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static Category GetInfo(int id)
        {
            var dic = GetInfos();
            Category info;
            if (dic.TryGetValue(id, out info))
                return info;
            return null;
        }

        #endregion

        #region 建立URL格式

        /// <summary>
        /// 建立URL格式
        /// </summary>
        /// <param name="model"></param>
        private void BuildUrlFormat(Category model)
        {
            var minfo = ModelManage.GetInfo(model.ModelId);
            if (model.TemplateFileName.IsNullOrEmpty())
            {
                return;
            }
            if (model.ShowPageTemplateFileName.IsNullOrEmpty())
            {
                return;
            }


            switch (model.CategoryUrlStyle)
            {
                case 0:
                    model.CategoryUrlFormat = "/Category/{CategoryId}/{PageNo}";
                    break;
                case 1:
                    model.CategoryUrlFormat = "{HtmlSavePath}/Category/{CategoryId}/{前缀}_{PageNo}{静态页扩展名}";
                    break;
                case 2:
                    model.CategoryUrlFormat = "{HtmlSavePath}/{栏目英文名称}/{前缀}_{PageNo}{静态页扩展名}";
                    break;
            }
            switch (model.UrlStyle)
            {
                case 0:
                    if (minfo.BaseModel == "Article")
                    {
                        model.ContentUrlFormat =
                            "{BaseModel}/Show/{CategoryId}/{ID}/{PageNo}";
                    }
                    else
                    {
                        model.ContentUrlFormat = "{BaseModel}/Show/{CategoryId}/{ID}";
                    }
                    break;
                case 1:
                    if (minfo.BaseModel == "Article")
                    {
                        model.ContentUrlFormat = "{HtmlSavePath}/Show/{CategoryId}/{前缀}{ID}_{PageNo}{静态页扩展名}";
                    }
                    else
                    {
                        model.ContentUrlFormat = "{HtmlSavePath}/Show/{CategoryId}/{前缀}{ID}{静态页扩展名}";
                    }
                    break;
                case 2:
                    if (minfo.BaseModel == "Article")
                    {
                        model.ContentUrlFormat = "{HtmlSavePath}/Show/{yyyyMM}/{前缀}{ID}_{PageNo}{静态页扩展名}";
                    }
                    else
                    {
                        model.ContentUrlFormat = "{HtmlSavePath}/Show/{yyyyMM}/{前缀}{ID}{静态页扩展名}";
                    }
                    break;
                case 3:
                    if (minfo.BaseModel == "Article")
                    {
                        model.ContentUrlFormat = "{HtmlSavePath}/Show/{yyyyMM/dd}/{前缀}{ID}_{PageNo}{静态页扩展名}";
                    }
                    else
                    {
                        model.ContentUrlFormat = "{HtmlSavePath}/Show/{yyyyMM/dd}/{前缀}{ID}{静态页扩展名}";
                    }
                    break;
            }

            StringBuilder sbCategoryFormat = new StringBuilder(model.CategoryUrlFormat);

            sbCategoryFormat.Replace("{HtmlSavePath}", StaticFilePath.ModelHtmlPath(minfo));
            string pageName =
                model.TemplateFileName.Substring(model.TemplateFileName.LastIndexOfAny(new[] { '/', '\\' }) + 1);
            pageName = pageName.Substring(0, pageName.LastIndexOf(".aspx", StringComparison.CurrentCultureIgnoreCase));

            sbCategoryFormat.Replace("{BaseModel}", minfo.BaseModel);
            sbCategoryFormat.Replace("{PageName}", pageName);
            sbCategoryFormat.Replace("{CategoryId}", model.Id.ToString());
            sbCategoryFormat.Replace("{栏目英文名称}", model.CategoryNameEN);
            if (string.IsNullOrEmpty(model.CategoryFilePrefix))
            {
                sbCategoryFormat.Replace("{前缀}_", model.CategoryFilePrefix);
            }
            else
            {
                sbCategoryFormat.Replace("{前缀}", model.CategoryFilePrefix);
            }
            sbCategoryFormat.Replace("{静态页扩展名}", model.CategoryFilePostfix);

            model.CategoryUrlFormat = sbCategoryFormat.ToString();

            StringBuilder sbContentFormat = new StringBuilder(model.ContentUrlFormat);
            sbContentFormat.Replace("{HtmlSavePath}", StaticFilePath.ModelHtmlPath(minfo));
            sbContentFormat.Replace("{BaseModel}", minfo.BaseModel);
            sbContentFormat.Replace("{CategoryId}", model.Id.ToString());
            sbContentFormat.Replace("{前缀}", model.FilePrefix);
            sbContentFormat.Replace("{静态页扩展名}", model.CategoryFilePostfix);

            model.ContentUrlFormat = sbContentFormat.ToString();
        }

        #endregion

        #region 栏目排序

        /// <summary>
        /// 栏目排序
        /// </summary>
        /// <param name="model"></param>
        [Logging("栏目排序，ID：{@p0.ID}，排序动作{@p0.OrderType}"), ExceptionCall]
        public void OrderByMove(Category model)
        {
            Dal.OrderByMove(model);

            ClearCache();
        }

        #endregion

        #region 清空该栏目的内容

        /// <summary>
        /// 清空该栏目的内容
        /// </summary>
        /// <param name="categoryId"></param>
        [Logging("清空栏目ID{@p0}下的数据"), ExceptionCall]
        public void Clear(int categoryId)
        {
            Dal.Clear(categoryId);

            ClearCache();
        }

        #endregion

        private void ClearCache()
        {
            CacheStorager.CMSCaches.Context.FlushAll();
        }

        #region 删除栏目

        /// <summary>
        /// 删除栏目
        /// </summary>
        /// <param name="categoryId"></param>
        [Logging("删除栏目，Id：{@p0}"), ExceptionCall]
        public Result Delete(int categoryId)
        {
            Result res = new Result();

            if (Dal.HaveData(categoryId) >= 1)
            {
                res.Errors = "该栏目下还有数据存在，请先清空栏目！";
                return res;
            }
            Dal.Delete(categoryId);

            ClearCache();
            return res;
        }

        #endregion

        #region 删除模型下所有栏目

        /// <summary>
        /// 删除模型下所有栏目
        /// </summary>
        /// <param name="modelId"></param>
        [Logging("删除ModelId={@p0}下的所有栏目"), ExceptionCall]
        public void Delete(byte modelId)
        {
            Dal.Delete(modelId);

            ClearCache();
        }

        #endregion

        #region 导航栏－－xxx_Manage.aspx中使用

        /// <summary>
        /// 导航栏－－xxx_Manage.aspx中使用
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public string CategoryPath(int categoryId)
        {
            IList<Category> list = GetFatherAndMe(categoryId);

            StringBuilder s = new StringBuilder();
            foreach (Category model in list)
            {
                s.Append(" → ");
                s.Append(model.CategoryName);
            }

            return s.ToString();
        }

        #endregion

        #region 绑定栏目控件

        /// <summary>
        /// 绑定栏目控件
        /// </summary>
        /// <param name="name"></param>
        /// <param name="type"></param>
        /// <param name="newListItem"></param>
        /// <param name="modelId"></param>
        public CategoryManage BindDDL(System.Web.UI.WebControls.ListControl name, BindOption type, string newListItem,
                            byte? modelId)
        {
            name.Items.Clear();
            IList<Category> treeViewList = new List<Category>();

            IList<Category> list = Dal.Bind_DDL(type, modelId);

            biuldTree(treeViewList, list, 0);

            foreach (var v in treeViewList)
            {
                var li = new System.Web.UI.WebControls.ListItem(v.CategoryName, v.Id.ToString());
                if (Convert.ToInt32(v.ParentId) == 0 && list.Any(x => x.ParentId == v.Id))
                {
                    li.Attributes["optgroup"] = v.CategoryName;
                }
                name.Items.Add(li);
            }
            if (string.IsNullOrEmpty(newListItem) == false)
            {
                name.Items.Insert(0, new System.Web.UI.WebControls.ListItem(newListItem, "0"));
            }

            return this;
        }

        #endregion

        #region 递归处理栏目

        /// <summary>
        /// 递归处理栏目
        /// </summary>
        /// <param name="treeViewList"></param>
        /// <param name="dataSouce"></param>
        /// <param name="parentId"></param>
        private void biuldTree(IList<Category> treeViewList, IEnumerable<Category> dataSouce, int parentId)
        {
            StringBuilder newCategoryName = new StringBuilder();
            var q = (from x in dataSouce where x.ParentId == parentId orderby x.OrderId select x).ToArray();
            if (q.Any())
            {
                int i = q[0].Path.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Length;
                for (int x = 1; x < i; x++)
                {
                    newCategoryName.Append("┆┄");
                }
            }

            foreach (var v in q)
            {
                v.CategoryName = newCategoryName + v.CategoryName;

                treeViewList.Add(v);
                biuldTree(treeViewList, dataSouce, v.Id);
            }
        }

        #endregion

        #region 该栏目是否被授权

        /// <summary>
        /// 该栏目是否被授权
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public static bool CheckAllowCategory(int categoryId)
        {
            if (categoryId == 0) return true;
            return Dal.GetCategoryList(UserManage.Current.UserID).Any(x => x.Id == categoryId);
        }

        #endregion

        #region 生成上传文件的物理路径

        /// <summary>
        /// 生成上传文件的物理路径
        /// </summary>
        /// <param name="categoryId">栏目ID</param>
        /// <param name="fileName">文件名</param>
        /// <param name="backGround">是否为后台</param>
        /// <returns></returns>
        public static string GetSavePath(int categoryId, string fileName, bool backGround)
        {
            Category model = GetInfo(categoryId);
            var mm = ModelManage.GetInfo(model.ModelId);

            CMSConfig config = CMSConfig.Instance();
            string filePath;
            if (backGround)
            {
                if (mm.AdminUploadPath.Split('|')[0] == "1") //以栏目上传目录为父目录
                {
                    filePath = HttpContext.Current.Server.MapPath(config.UpLoadFolder);
                }
                else //以CMS上传目录为父目录
                {
                    filePath = HttpContext.Current.Server.MapPath(config.UpLoadFolder);
                }


                if (mm.AdminUploadPath.Split('|')[1].Length > 0)
                {
                    filePath = String.Concat(filePath,
                        DateTime.Now.ToString(mm.AdminUploadPath.Split('|')[1],
                            System.Globalization.DateTimeFormatInfo.InvariantInfo), @"\", Guid.NewGuid().ToString(),
                        fileName);
                }
                else
                {
                    filePath = String.Concat(filePath, Guid.NewGuid().ToString(), fileName);
                }
            }
            else
            {
                if (mm.MemberUploadPath.Split('|')[0] == "1") //以栏目上传目录为父目录
                {
                    filePath = HttpContext.Current.Server.MapPath(config.UpLoadFolder);
                }
                else //以CMS上传目录为父目录
                {
                    filePath = HttpContext.Current.Server.MapPath(config.UpLoadFolder);
                }

                if (mm.MemberUploadPath.Split('|')[1].Length > 0)
                {
                    filePath = String.Concat(filePath,
                        DateTime.Now.ToString(mm.MemberUploadPath.Split('|')[1],
                            System.Globalization.DateTimeFormatInfo.InvariantInfo), @"\", Guid.NewGuid().ToString(),
                        fileName);
                }
                else
                {
                    filePath = String.Concat(filePath, Guid.NewGuid().ToString(), fileName);
                }
            }

            filePath = filePath.Replace("/", @"\");

            if (System.IO.Directory.Exists(filePath) == false)
            {
                System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(filePath));
            }

            return filePath;
        }

        #endregion

        #region 合并栏目

        /// <summary>
        /// 合并栏目
        /// </summary>
        /// <param name="oldCategoryId"></param>
        /// <param name="newCategoryId"></param>
        /// <param name="childCategory"></param>
        /// <param name="deleteCategory"></param>
        public Result MergeCategory(int oldCategoryId, int newCategoryId, bool childCategory, bool deleteCategory)
        {
            Result resu = new Result();
            if (oldCategoryId == 0)
            {
                resu.Errors = "请选择栏目";
                return resu;
            }
            if (newCategoryId == 0)
            {
                resu.Errors = "请选择栏目";
                return resu;
            }
            if (oldCategoryId == newCategoryId)
            {
                resu.Errors = "不能在同一个栏目下执行";
                return resu;
            }

            Result s = Dal.MergeCategory(oldCategoryId, newCategoryId, childCategory, deleteCategory);
            if (string.IsNullOrEmpty(resu.Errors) == false)
            {
                resu.Errors = s.Errors;
            }

            ClearCache();

            return resu;
        }

        #endregion

        #region 批量更新

        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="selected"></param>
        /// <param name="values"></param>
        /// <param name="ids"></param>
        public Result BatchUpData(List<bool> selected, List<object> values, List<int> ids)
        {
            Result res = new Result();
            if (selected.Any(x => x) == false)
            {
                res.Errors = "至少要选择一个！";
                return res;
            }


            Dal.BatchUpData(selected, values, ids);
            ClearCache();

            foreach (var v in _alllist.Where(x => ids.Contains(x.Key)).Select(x => x.Value))
            {
                Save(v, new List<string>());
            }
            return res;
        }

        #endregion

        #region 移动栏目

        /// <summary>
        /// 移动栏目
        /// </summary>
        /// <param name="id"></param>
        /// <param name="newPid"></param>
        public Result Move(string id, string newPid)
        {
            Result res = new Result();
            if (id.Length == 0)
            {
                res.Errors = "请选择源栏目。";
                return res;
            }
            if (id == newPid)
            {
                res.Errors = "不准移动到栏目本身。";
                return res;
            }
            int iNewPid;
            if (int.TryParse(newPid, out iNewPid))
            {
                Dal.Move(int.Parse(id), iNewPid);

                ClearCache();
            }
            else
            {
                res.Errors = "请选择目标栏目。";
                return res;
            }
            return res;
        }

        #endregion

        #region 获取全部子孙ID

        /// <summary>
        /// 获取全部子孙ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static IEnumerable<int> GetDescendantIds(int id)
        {
            return Dal.GetDescendantIds(id);
        }

        /// <summary>
        /// 获取全部子孙ID
        /// </summary>
        /// <param name="modelId">模型id</param>
        /// <returns></returns>
        public static IEnumerable<int> GetDescendantIDsByModelId(byte modelId)
        {
            return Dal.GetInfos(modelId).Select(x => x.Id);
        }

        #endregion

        #region 取得孩子栏目

        /// <summary>
        /// 取得孩子栏目
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        public static IEnumerable<Category> GetChildren(int parentId)
        {
            var list = Dal.GetChildren(parentId);
            list.ForEach(x => x.Link = StaticFilePath.CategoryUrl(x));
            return list;
        }

        #endregion

        #region 读取数据库里所有栏目

        /// <summary>
        /// 读取数据库里所有栏目
        /// </summary>
        /// <returns></returns>
        public static Dictionary<int, Category> GetInfos()
        {
            if (_alllist == null)
            {
                _alllist = CategoryDal.Alllist;
                foreach (var kp in _alllist)
                {
                    kp.Value.Link = StaticFilePath.CategoryUrl(kp.Value);
                }
            }
            return _alllist;
        }

        #endregion

        #region 通过多个id获取栏目

        /// <summary>
        /// 通过多个id获取栏目
        /// </summary>
        /// <param name="categoryIds"></param>
        /// <returns></returns>
        public IList<Category> GetInfoByCategoryIds(string categoryIds)
        {
            int[] IDs = MyConvert.ConvertToArr(categoryIds.Split(','));

            return (from x in GetInfos() where IDs.Contains(x.Key) select x).Select(x => x.Value).ToList();
        }

        #endregion

        #region 查找所有上级极其自己

        /// <summary>
        /// 查找所有上级极其自己
        /// </summary>
        /// <param name="categoryId">栏目id</param>
        /// <returns></returns>
        public IList<Category> GetFatherAndMe(int categoryId)
        {
            IList<Category> list = Dal.GetFatherAndMe(categoryId);
            list.ForEach(x => x.Link = StaticFilePath.CategoryUrl(x));
            return list;
        }

        #endregion

        #region 栏目js数据源

        /// <summary>
        /// 栏目js数据源
        /// </summary>
        /// <param name="id">栏目ID</param>
        /// <returns></returns>
        public IList<TreeNode> CategoryTreeList(int id)
        {
            IEnumerable<Category> all = GetInfos().Values;
            IList<TreeNode> tns = new List<TreeNode>();

            foreach (var v in all.Where(x => x.ParentId == id).OrderBy(x => x.OrderId))
            {
                tns.Add(new TreeNode(v.Id.ToString(), v.CategoryName)
                {
                    State = all.Any(x => x.ParentId == v.Id) ? "closed" : "open",
                    CustomField1 = v.Id.ToString(),
                    CustomField2 = v.Id.ToString(),
                    CustomField3 = v.UrlStyle.ToString(),
                    CustomField4 = v.CategoryUrlStyle.ToString(),
                    CustomField5 = v.Id.ToString()
                });
            }

            return tns;
        }

        #endregion

        #region 获取栏目路径

        /// <summary>
        /// 获取栏目路径
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public static string GetPath(string categoryId)
        {
            return GetInfos()[int.Parse(categoryId)].Path;
        }

        #endregion

        #region 获取管理员有权限的栏目

        /// <summary>
        /// 获取管理员有权限的栏目
        /// </summary>
        /// <returns></returns>
        public IList<Category> GetCategoryList()
        {
            return Dal.GetCategoryList(UserManage.Current.UserID);
        }

        #endregion
    }
}